'use strict';

/**
 * @class sf.b2c.mall.framework.multiple.comm
 * @description comm的合并通信
 * @example
 *
 * ```
 * var webLogin = new SFUserWebLogin(utils.testData.user4Login);
 *
 *     webLogin
 *       .sendRequest()
 *       .done(function(loginResult) {
 *       })
 *       .fail(function(errorCode) {
 *         errorCode.should.equal(0);
 *         done();
 *       })
 *       .then(function(loginResult) {
 *         request_a = new SFGetSKUInfo({sku: 1});
 *         request_b = new SFGetUserInfo();
 *
 *         var mComm = new SFFrameworkMultipleComm([request_a, request_b]);
 *         mComm.setData([request_a.data, request_b.data]);
 *         return mComm.sendRequest();
 *       })
 *       .done(function(message) {
 *         console.log(message)
 *         message.length.should.equal(2)
 *         message[0].skuId.should.equal('1')
 *         message[1].mailId.should.equal(utils.testData.user4Login.accountId)
 *         done();
 *       })
 *       .fail(function(stat) {
 *         for(var i in stat.stateList){
 *           stat.stateList[i].code.should.equal(0);
 *         }
 *         done();
 *       })
 * ```
 */

define(
  [
    'underscore',
    'sf.b2c.mall.framework.comm',
    'sf.b2c.mall.business.config',
    'sf.b2c.mall.api.security.type'
  ],
  function ( _, SFComm, SFBizConfig, SecurityType) {

    var ERROR_CODE_TOKEN_ERROR = -360;
    var ERROR_CODE_TOKEN_EXPIRE = -300;
    var ERROR_CODE_SIGNATURE_ERROR = -180;
    var ERROR_CODE_ACCESS_DENIED = -160;

    var TOKEN_AND_SIGNATURE_ERROR_GROUP = [
      ERROR_CODE_TOKEN_ERROR,
      ERROR_CODE_TOKEN_EXPIRE,
      ERROR_CODE_SIGNATURE_ERROR,
      ERROR_CODE_ACCESS_DENIED
    ];

    return SFComm.extend({

      /**
       * @override
       * @function sf.b2c.mall.framework.multiple.comm.init
       * @description 在init方法中传入comm的队列
       * @param  {List<Comm>} comms comms 需要合并的接口Array
       */
      init: function (comms) {
        this.buildApi(comms);
      },

      /**
       * @function sf.b2c.mall.framework.multiple.comm.buildApi
       * @description 为multiple创建api对象
       * @param  {List<Comm>} comms 需要合并的接口Array
       */
      buildApi: function (comms) {
        var apis = _.pluck(comms, 'api');

        // 拼接_mt字段饿方法请求
        var _mt_arr = _.pluck(apis, 'METHOD_NAME');
        this.api.METHOD_NAME = _mt_arr.join(',');

        // 获取SecurityType
        var securityType = {
          code: -1,
          name: null
        };
        _.each(apis, function(api){
          var st = SecurityType[api.SECURITY_TYPE];
          if (st.code > securityType.code) {
            securityType = st;
          }
        });
        this.api.SECURITY_TYPE = securityType.name;

        // 设置Data
        this.api.REQUIRED = _.pluck(apis, 'REQUIRED');
        this.api.OPTIONAL = _.pluck(apis, 'OPTIONAL');
      },

      /**
       * @override
       * @function sf.b2c.mall.framework.multiple.comm.buildRequestData
       * @description 对multiple的comms做数据处理
       */
      buildRequestData: function () {
        if (this.api) {
          var requestData = {};

          _.extend(requestData, {
            '_mt': this.api.METHOD_NAME
          });

          _.extend(requestData, this.api.COMMON);

          var that = this;

          var key;
          _.each(this.api.REQUIRED, function(apis, index){
            for (key in that.api.REQUIRED[index]) {
              requestData[index + '_' + key] = that.data[index][key];
            }
          });

          _.each(this.api.OPTIONAL, function(apis, index){
            for (key in that.api.OPTIONAL[index]) {
              requestData[index + '_' + key] = that.data[index][key];
            }
          });

          return requestData;
        }
      },

      /**
       * @override
       * @function sf.b2c.mall.framework.multiple.comm.access
       * @description 返回的参数是否正确
       * @param  {Map}      response          服务端返回的信息
       * @param  {Boolean}  isForceUserLogin  是否需要强制登陆
       */
      access: function(responses, isForceUserLogin) {
        if (_.isArray(responses.content)) {
          var that = this;
          var result = true;
          _.each(responses.content, function(response, index){
            result = result && that._access(responses, index, isForceUserLogin);
          });
          return result;
        }else{
          return this._access(responses, 0, isForceUserLogin);
        }
      },

      _access: function (response, index, isForceUserLogin) {
        if (response.stat.code === 0 && response.content[index] && response.stat.stateList[index].code === 0) {
          return true;
        } else if (_.contains(TOKEN_AND_SIGNATURE_ERROR_GROUP, response.stat.code) && isForceUserLogin) {
          this.goToLogin();
        } else {
          return false;
        }
      },

      /**
       * @function sf.b2c.mall.framework.request
       * @param  {Map}     data             请求参数
       * @param  {Boolean} isForceUserLogin 是否需要强制登陆
       * @return {can.Deferred}
       */
      request: function(data, isForceUserLogin) {
        var def = can.Deferred();

        var successCallback = function(response) {
          if (response && response.stat) {
            that.serverTime = response.stat.systime;
          }

          if (that.access(response, isForceUserLogin)) {
            that.afterRequest(data._mt, response.content);
            def.resolve(response.content);
          } else {
            if (response.stat.stateList.length == 0) {

              // -180则清空所有storage
              if (response.stat.code == ERROR_CODE_SIGNATURE_ERROR) {
                store.clear();
                that.goToLogin();
              }

              def.reject(response.stat.code);
            } else {
              def.reject(response.stat.stateList[0].code, response.stat.stateList[0].msg);
            }
          }
        }

        var failCallback = function(error) {
          def.reject(error);
        }

        var that = this;

        $.ajax({
            url: SFBizConfig.setting.api.url,
            type: 'post',
            contentType: "application/x-www-form-urlencoded; charset=UTF-8",
            data: that.sign(data),
            fixture: that.fixture,
            success: function(response) {
              successCallback(response);
            },
            fail: function(error) {
              failCallback(error);
            }
          })
          .done(function(response) {
            successCallback(response);
          })
          .fail(function(error) {
            failCallback(error);
          });

        return def;
      },

    });
});